package cn.tianyigps.obd.utils;


import cn.tianyigps.obd.beans.OBD;
import cn.tianyigps.obd.beans.StandardModel;
import cn.tianyigps.obd.constant.AlarmConstant;
import cn.tianyigps.obd.constant.Format;
import com.google.gson.Gson;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Created with IntelliJ IDEA
 * Created By cuiguibin
 * Date: 2018/5/25
 * Time: 9:40
 * Description:部标协议数据解析类
 * (适用OCAR-3，载重设备，唯一区别就是ocar-3有车架号、vin、非法拆除，剩下的都通用，区分通过扩展位区分)
 */
public class StrConvertUtil {

    static Logger log = LogManager.getLogger(StrConvertUtil.class);

    public static List<StandardModel> analysisByM5BStr(String str, String ipAddress, String uniqueIden, String equipmentId) {
        List<StandardModel> standardModelList = new ArrayList<>();
        //定位数据包的解析
        if ("7E0200".equals(uniqueIden.toUpperCase())) {
            StandardModel standardModel = new StandardModel();
            getLocMessage(ipAddress, equipmentId, str, standardModel,26);
            try {
                Map<String, String> extend = getExtend(str,94);
                standardModel.setExtend(extend);
            } catch (Exception e) {
                log.error("扩展数据解析错误：  {}",str);
                log.error("errorLog：  {}",e.getMessage());
                e.printStackTrace();
            }
            standardModelList.add(standardModel);
        } else if ("7E0704".equals(uniqueIden.toUpperCase())) {  //0704批量定位数据包
            //补全的定位点的个数
            Integer numLoc = Integer.parseInt(str.substring(26, 30), 16);
            //将每个定位点的数据都解析出来
            if (numLoc > 0) {
                //判断是否为补全数据
                String locCompletion = str.substring(30, 32);
//                M5BEquipmentConfig config = new M5BEquipmentConfig();
//                Integer start = 32;
                Integer start = 32;
                for (int i = 0; i < numLoc; i++) {
                    StandardModel standardModel = new StandardModel();
                    //每个定位点的数据包的长度
                    Integer len = Integer.parseInt(str.substring(start, start + 4), 16);
                    commonFiledsAssign(standardModel, str, ipAddress);
                    //设置每一个定位包的想改定位相关的信息
                    getLocMessage(ipAddress, equipmentId, str, standardModel,start + 4);
                    Gson gson = new Gson();
                    if (null == standardModel.getOther()) {
                        standardModel.setOther(gson.toJson(new HashMap<String, String>()));
                    }
                    Map<String, String> map = gson.fromJson(standardModel.getOther(), Map.class);
                    //是否为补传数据
                    if ("00".equals(locCompletion)) {
                        map.put("locCompletion", "0");
                    } else {
                        map.put("locCompletion", "1");
                    }
                    String substring = str.substring(start + 4, start + 4 + len * 2 + 4);
                    try {
                        Map<String, String> extend = getExtend(str,-1);
                        standardModel.setExtend(extend);
                    } catch (Exception e) {
                        log.error("批量扩展数据解析错误：  {}",str);
                        log.error("errorLog：  {}",e.getMessage());
                        e.printStackTrace();
                    }
                    standardModel.setOther(gson.toJson(map));
                    standardModelList.add(standardModel);
                    //下一个定位点数据的解析的起始位
                    start += len * 2 + 4;
                }
            }
        }
        //其他包暂定都当作心跳包
        else {
            StandardModel standardModel = new StandardModel();
            //其他的数据包共有数据
            commonFiledsAssign(standardModel, str, ipAddress);
            standardModel.setFormat(Format.HEART_PACKAGE);
            standardModelList.add(standardModel);
        }

        return standardModelList;
    }


    /**
     * @Description: 获取定位数据相关信息  7E0200 stat = 26  7E0704  36
     * @params: [ipAddress, equipmentId, str, standardModel]
     * @return: void
     * @auther: cuiguibin
     * @date: 2018/11/12 11:12
     */
    private static void getLocMessage(String ipAddress, String equipmentId, String str, StandardModel standardModel,int start) {

        commonFiledsAssign(standardModel, str, ipAddress);
        standardModel.setAlarm(StringAnalysisUtil.getAlarm(str, start,start + 8));
        Map<String, String> map = StringAnalysisUtil.getLocationStatus(str, start + 8,start + 16);
        //判断定位类型是gps还是基站
        standardModel.setLocationType(("1").equals(map.get("gpsLocation")) ? "00" : "01");
        Gson gson = new Gson();
        standardModel.setLocStatus(map.get("gpsLocation"));
        map.remove("gpsLocation");
        standardModel.setEquipmentStatus(gson.toJson(map));
        standardModel.setGpsLatitude(StringAnalysisUtil.getLonLat(str, start + 16,start + 24));
        standardModel.setGpsLongitude(StringAnalysisUtil.getLonLat(str, start + 24,start + 32));
        standardModel.setFormat(Format.LOCATION_PACKAGE);
        standardModel.setVoltage(StringAnalysisUtil.getVoltage(str));
        //当为gps定位时设置速度、航向、上报时间
        if (Optional.ofNullable(standardModel.getLocationType()).isPresent() && "00".equals(standardModel.getLocationType())) {
            standardModel.setSpeed(StringAnalysisUtil.getSpeed(str, start + 36,start + 40));
            standardModel.setHeading(StringAnalysisUtil.getHeading(str, start + 40,start + 44));
            standardModel.setReportTime(StringAnalysisUtil.getReportTime(str, start + 44,start + 56));
        }
        standardModel.setOther(StringAnalysisUtil.getOther(str, equipmentId, standardModel.getSpeed()));
        //获取M5和M5的定位基站数据（通用Q3解析方法）
        String result = StringAnalysisUtil.getBaseStation(str);
        //当基站数据存在时
        if (!StringUtil.isNullOrEmpty(result)) {
            String lac = StringAnalysisUtil.getDecimalString(result.substring(0, 4));
            String cellId = StringAnalysisUtil.getDecimalString(result.substring(4, 8));
            if (!StringUtil.isNullOrEmpty(lac) && !StringUtil.isNullOrEmpty(cellId) && !"0".equals(lac) && !"0".equals(cellId)) {
                standardModel.setLac(lac);
                standardModel.setCellId(cellId);
            }
        }
        //查看设备是否为断电报警数据
//        standardModel.setAlarm(StringAnalysisUtil.getAlarm(str, 26,34));
        if (!StringUtils.isEmpty(standardModel.getAlarm())) {
            standardModel.setFormat(Format.ALARM_PACKAGE);
        } else {
            //当设备为拆除装状态时
            if (Optional.ofNullable(standardModel.getOther()).isPresent()) {
                Integer illegalDemolitionIndex = standardModel.getOther().lastIndexOf("illegalDemolition");
                if (illegalDemolitionIndex != -1) {
                    Map<String, String> map1 = gson.fromJson(standardModel.getOther(), Map.class);
                    String alarm = map1.get("illegalDemolition");
                    if ("1".equals(alarm)) {
                        standardModel.setAlarm(AlarmConstant.ILLEGAL_DISMANTLE_ALARM);
                        standardModel.setFormat(Format.ALARM_PACKAGE);
                    }
                }
            }
        }
    }

    /**
     * @param: str
     * @return Map<String,Object>
     * @author cui.guibin
     * @date 2019/4/1 17:51
     */
    private static Map<String,String> getExtend(String str,int ebIndex) {
        if (ebIndex < 0)
            ebIndex = str.indexOf("0104") + 12;
        String extendStr = str.substring(ebIndex, str.length() - 4);
        Map<String, String> extent = new HashMap<>();
        while (extendStr.length() > 0) {
            String match = extendStr.substring(0, 2);
            String lengthStr = extendStr.substring(2, 4);
            Integer length = Integer.parseInt(StringAnalysisUtil.getDecimalString(lengthStr));
            String substring = extendStr.substring(4, 4 + length * 2);
            extendStr = extendStr.replace(match + lengthStr + substring, "");
            switch (match) {

                case "EB":
                    break;

                case "E1":
                    Map<String, String> alarm = ExtendUtil.getAlarm(substring);
                    if (Optional.ofNullable(alarm).isPresent() && !alarm.isEmpty())
                        extent.putAll(alarm);
                    break;
                case "E2":
                    Map<String, String> obd = ExtendUtil.getOBD(substring);
                    if (Optional.ofNullable(obd).isPresent() && !obd.isEmpty())
                        extent.putAll(obd);
                    break;
                case "E3":
                    Map<String, String> fault = ExtendUtil.getFault(substring);
                    if (Optional.ofNullable(fault).isPresent() && !fault.isEmpty())
                        extent.putAll(fault);
                    break;
                case "E4":
                    Map<String, String> carInfo = ExtendUtil.getCarInfo(substring);
                    if (Optional.ofNullable(carInfo).isPresent() && !carInfo.isEmpty())
                        extent.putAll(carInfo);
                    break;
                case "E5":
                    Map<String, String> versionInfo = ExtendUtil.getVersionInfo(substring);
                    if (Optional.ofNullable(versionInfo).isPresent() && !versionInfo.isEmpty())
                        extent.putAll(versionInfo);
                    break;
                case "E6":
                    Map<String, String> base = ExtendUtil.getBase(substring);
                    if (Optional.ofNullable(base).isPresent() && !base.isEmpty())
                        extent.putAll(base);
                    break;
                case "E7":
                    String voltage = ExtendUtil.getVoltage(substring);
                    if (Optional.ofNullable(voltage).isPresent() && !voltage.isEmpty())
                        extent.put("voltage", voltage);
                    break;
                case "F1":
                    extent.put("rapidDecelEvent","1");
                    break;
                case "F2":
                    extent.put("rapidAccelEvent","1");
                    break;
                case "F3":
                    extent.put("sharpTurnEvent","1");
                    break;
                case "F5":
                    extent.put("brakeEvent","1");
                    break;
                case "F6":
                    extent.put("collisionEvent","1");
                    break;
                default:
            }
        }
        return extent;
    }


    /**
     * @Description: 共有数据解析
     * @params: [model, str, ipAddress]
     * @return: cn.tianyigps.tianyigpsmongopojo.model.StandardModel
     * @auther: yangxl
     * @date: 2018/11/12 11:35
     */
    private static void commonFiledsAssign(StandardModel model, String str, String ipAddress) {
        model.setEquipmentType("TCP")
                .setStartBit(StringAnalysisUtil.getSubString(str,0,2 ))
                .setProtocolNumber(StringAnalysisUtil.getSubString(str, 2,6))
                .setEquipmentId(StringAnalysisUtil.getSubString(str, 10,22).replaceFirst("^0*", ""))
                .setIpAddress(ipAddress)
                .setOriginalData(str)
                .setCreateTime(new Date())
                .setPowerType("wired");
    }
    public static void main(String[] args) {
        String strData ="7E070401AB016800000007004D0006010054000000000000000301DD675E073E0AD000000320012219060614384701040000021BE22C007FD7B0000701000090073E4C667C43570000000000FE036E00000000000003FF0361020000CF8100001D5AE70200910054000000000000000301DD7174073DF0980000033E011E190606143916010400000222E22C007FD7B0000701000091079D50647D024340000000000139038E00000000000003FF02AD020000D23400001D8AE70200900026000000000000000301DD71A6073DEDC0000003520114190606143919010400000223E70200900054000000000000000301DD707A073DE0D80000024E0104190606143936010400000226E22C007FD7B000070100009705D43A647D0143500000000000B003AE00000000000003F70249020000D3CF00001D9DE70200900026000000000000000301DD6FE4073DDF080000026200F7190606143939010400000226E70200900054000000000000000301DD6EB8073DDC880000026200EB190606143943010400000227E22C007FD7B0000701000097061F40647D01434C0000000000B003AE00000000000003F70249020000D47C00001DACE70200900D7E";
        String s = "7E0200010E0141441840310003000000000000000101DE5958073D188000000000000819040422243201040000022DEB26002400A901CC000618C93E8A2F18C93E892E18C93E832418C93E871F18C93E801F18C93E6D1CE228007FC5B000070100008E0000003D68376500000000000000000000044503BB020000A05D0000116CE30100E702008EE42A0000000000044C534A144902014C534A573236373631461000015537314E303937333230000000000000E565474944414735303430313031323031392D30332D32364F4341522D35202032353033442020204254303120202020343630303430373739363032323837383938363032423730393137303036333232383700000000000000000000000000000000000000008D7E";
        String s2 = "7E020000540168000000070058000000000000000301DE1FAC073CBFB80000010401491906061126450104000000E0E22C007FD7B000070100009406BC185E7B43600000000000A8047A00000000000003F702C10200004E0D00000F9BE702008E4F7E";
        String transData = strData;
        if (strData.contains("7D01"))
            transData = transData.replaceAll("7D01","7D");
        if (strData.contains("7D02"))
            transData = transData.replaceAll("7D02","7E");
        if (!transData.endsWith("7E"))
            transData = transData + "7E";
        List<StandardModel> standardModels = StrConvertUtil.analysisByM5BStr(transData, "111", "7E0704", "16800000007");

    }

}
